#ifndef __KEW_INTERMEDIATECODE_H__
#define __KEW_INTERMEDIATECODE_H__

#include <kew/kew.h>

enum KewCodeReferenceType {
    EXPRESSION_REF,
    ARGUMENT_REF,
    CAPTURE_REF,
    BUILT_IN_REF,
    SELF_REF
};

enum KewCodeInstructionType {
    SEND,
    BLOCK_INSTANTIATION,
    OBJECT_INSTANTIATION,
    STRING_CONSTANT,
    INTEGER_CONSTANT,
    BEGIN_OBJECT_INSTANTIATION,
    END_OBJECT_INSTANTIATION,
    FLOAT_CONSTANT
};

typedef struct _KewCodeBlock KewCodeBlock;
typedef struct _KewCodeReference KewCodeReference;
typedef struct _KewCodeInstruction KewCodeInstruction;

struct _KewCodeBlock {
    KewCallShape call_shape;
    unsigned number_of_capture_slots;
    unsigned number_of_instructions;
    KewCodeInstruction *instructions;
};

struct _KewCodeReference {
    unsigned type;
    unsigned slot;
};

struct _KewCodeInstruction {
    unsigned type;
    union {
        struct {
            KewCodeReference receiver_reference;
            KewSelector selector;
            KewCallShape call_shape;
            KewCodeReference *argument_references; /* we only need actuals here, so no results */
        } send;
        
        struct {
            /* FIXME: hold block id */
        } block_instantiation;

        struct {
            /* FIXME: hold object id */
        } object_instantiation;

        struct {
            KewObject *value;
        } constant;

        struct {
        } begin_object_instantiation;

        struct {
        } end_object_instantiation;
    } data;
};

#endif
